﻿#include<iostream>
using namespace std;


//1.c++11对列表的改造 企图用{}来构造一切
//#include<initializer_list>
//class A {
//public:
//	A(int a = 1, int b = 2)
//		
//		:_a(a), _b(b)
//	{
//		cout << "A()" << endl;
//	}
//
//	template<class T>
//	A(const initializer_list<T>& itl) {
//		cout << "A(const initializer_list<T>&)" << endl;
//	}
//
//
//private:
//	int _a;
//	int _b;
//};

//class B {
//public:
//
//	B(const initializer_list<int>& itl) {
//		auto it = itl.begin();
//		int i = 0;
//		while (it != itl.end()) {
//			pa[i++] = *it;
//			++it;
//		}
//	}
//private:
//	int* pa = new int[10];
//};

//int main() {
//	//int a{ 2 };
//	////如果没有initializer_list的话，走的是隐式类型转换  反之走的是initializer_list的构造
//	//A aa  = { 1,2 };
//	////可以省略等号
//
//	/*A& aa1 = aa;
//	const A& aa2{ 1,2 };*/
//
//
//	////走initializer_list的构造
//	//B b = { 1,2,3,4,5,6,7,8,9,10 };
//	
//	return 0;
//}

//int main() {
//
//	int a = 10;
//	
//	int& ra = a;//左值引用 -> 左值
//	int&& rb = 20;//右值引用 -> 右值
//
//	const int& rc = 20;//const左值引用 -> 右值
//	int&& rd = move(a);//右值引用 -> 左值move到的右值
//
//	const int b = 50;
//	//int&& rrb = move(b);
//
//	return 0;
//}

//int main() {
//	int a = 10l;
//
//	int&& r0 = 20;
//	int&& r1 = move(a);
//
//	r0 = 30;
//	r1 = 150;
//
//	cout << r0 << " " << r1 << " " << a << endl;
//
//	return 0;
//}

//class M {
//public:
//
//	/*M(int a = 0, int b = 0)
//		:_a(a), _b(b)
//	{
//		cout << "M()" << endl;
//	}*/
//
//	/*M(const M& mm) {
//		cout << "M(const M& mm)" << endl;
//		_a = mm._a;
//		_b = mm._b;
//	}*/
//private:
//	int _a;
//	int _b;
//};
//
//int main() {
//
//	M mm = { 1,2 };
//	int a{ 10 };
//	double b{ 10.5 };
//
//	string str{ "abcdef" };
//
//	cout << a << " " << b << " " << str << endl;
//	
//	return 0;
//}


//左值和右值
//int main() {
//
//	int a = 10;
//	int b = 20;
//
//	//int& c = a + b;
//	//这个a + b其实是临时变量，具有常性(也就是右值)   除此之外还右匿名对象 临时对象
//
//	//1.
//	const int& c = a + b;//const引用
//
//	//2.
//	int&& d = a + b;//右值引用
//
//	/*a + b = 50;*/
//
//	//d的类型是右值引用  但是本身可以进行修改 是左值
//	d = 30;
//	cout << c << " " << d << endl;
//
//	cout << &d << endl;
//
//	
//	const int&& aa = move(a + b);
//
//
//
//	return 0;
//}


//参数匹配
//class Myclass {
//public:
//
//	void func(int& r1) {
//		cout << "void func(int&)" << endl;
//	}
//
//	void func(const int& r2) {
//		cout << "void func(const int&)" << endl;
//	}
//
//	void func(int&& r3) {
//		cout << "void func(int&&)" << endl;
//	}
//
//	void func(const int&& r4) {
//		cout << "void func(const int&&)" << endl;
//	}
//
//private:
//	int _a = 0;
//	int _b = 0;;
//};
//
//int main() {
//
//	int a = 20;
//	int& r1 = a;
//	const int& r2 = a;
//	int&& r3 = move(a);
//	const int&& r4 = move(a);
//
//	Myclass A;
//	/*A.func(r1);
//	A.func(r2);
//	这两个调用的是左值？ 为什么？ 因为右值引用本身的特性是左值
//	A.func(r3);
//	A.func(r4);*/
//
//
//	int num = 30;
//	const int nnum = 10;
//	A.func(num);
//	A.func(nnum);
//	A.func(num + nnum);
//	A.func(forward<const int>(r4));
//	
//	return 0;
//
//	
//}


//class Derive {
//public:
//	void func(int& x) {
//		cout << "func(int& x)" << endl;
//	}
//
//	void func(const int& x) {
//		cout << "func(const int& x)" << endl;
//	}
//
//	void func(int&& x) {
//		cout << "func(int&& x)" << endl;
//	}
//
//private:
//	int _a = 0;
//	int _b = 0;
//
//};
//
//
//int main() {
//
//	int a = 10;
//	const int b = 20;
//	Derive d;
//	d.func(a);
//	d.func(b);
//	d.func(30);
//
//	int&& r = 30;
//	d.func(r);
//
//
//	return 0;
//}



//int main() {
//
//	typedef int& IntLeftRef;
//	typedef int&& IntRightRef;
//
//	int a = 10;
//
//	//左值引用和左值引用折叠 -> 左值引用
//	IntLeftRef& R1 = a;
//	//IntLeftRef& R1 = 10;//报错 因为左值引用不能直接引用右值
//
//	//左值引用和右值引用折叠 -> 左值引用
//	IntLeftRef&& R2 = a;
//	//IntLeftRef&& R2 = 10;//报错 因为左值引用不能直接引用右值
//
//	//右值引用和左值引用折叠 -> 左值引用
//	IntRightRef& R3 = a;
//	//IntRightRef& R3 = 10;//报错 因为左值引用不能直接引用右值
//
//	//右值引用和右值引用折叠 -> 右值引用
//	//IntRightRef&& R4 = a; //因为右值引用不能直接引用左值
//	IntRightRef&& R4 = 10;
//
//	return 0;
//}


//// 由于引用折叠限定，f1实例化以后总是一个左值引用
//template<class T>
//void f1(T& x)
//{}
//// 由于引用折叠限定，f2实例化后可以是左值引用，也可以是右值引用
//template<class T>
//void f2(T&& x)
//{}
//
//int main() {
//
//	int n = 0;
//
//	// 没有折叠->实例化为void f1(int& x)
//	f1<int>(n);
//	//f1<int>(0); // 报错
//	
//	// 折叠->实例化为void f1(int& x)
//	f1<int&>(n);
//	//f1<int&>(0); // 报错
//	
//	// 折叠->实例化为void f1(int& x)
//	f1<int&&>(n);
//	//f1<int&&>(0); // 报错
//	
//	// 折叠->实例化为void f1(const int& x)
//	f1<const int&>(n);
//	f1<const int&>(0);
//
//	// 折叠->实例化为void f1(const int& x)
//	f1<const int&&>(n);
//	f1<const int&&>(0);
//
//	// 没有折叠->实例化为void f2(int&& x)
//	//f2<int>(n); // 报错
//	f2<int>(0);
//
//	// 折叠->实例化为void f2(int& x)
//	f2<int&>(n);
//	//f2<int&>(0); // 报错
//
//	// 折叠->实例化为void f2(int&& x)
//	//f2<int&&>(n); // 报错
//	f2<int&&>(0);
//
//	return 0;
//}




//template<class T>
//void Function(T&& t)
//{
//	int a = 0;
//	T x = a;
//	//x++;
//	cout << &a << endl;
//	cout << &x << endl << endl;
//}
//int main()
//{
//	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(10); // 右值
//	//&a和&x答案不一样
//
//	int a;
//
//	// a是左值，推导出T为int&，引用折叠，模板实例化为void Function(int& t)
//	Function(a); // 左值
//	//&a和&x答案一样
//	
//	// std::move(a)是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(std::move(a)); // 右值
//	//&a和&x答案不一样
//
//
//	const int b = 8;
//	// b是左值，推导出T为const int&，引用折叠，模板实例化为void Function(const int&t)
//	// 所以Function内部会编译报错，x不能++
//		Function(b); // const 左值
//	//&a和&x答案一样 但是x++就报错 因为move后不能改变const性
//
//	// std::move(b)右值，推导出T为const int，模板实例化为void Function(const int&&t)
//	// 所以Function内部会编译报错，x不能++
//		Function(std::move(b)); // const 右值
//	//&a和&x答案不一样   x也是不能++
//
//	return 0;
//}


//void f1(int&& x) {
//	cout << "void f1(int&&)" << endl;
//}
//
//void f1(int& x) {
//	cout << "void f1(int&)" << endl;
//}
//
//template<class T>
//void f(T&& x) {
//	f1(x);
//}
//
//int main() {
//
//	int a = 10;
//	f<int&>(a);
//
//	f<int&&>(10);
//
//	return 0;
//}



//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//template<class T>
//void Function(T&& t)
//{
//	Fun(forward<T>(t));
//}
//
//int main()
//{
//	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(10); // 右值
//
//	int a;
//
//	// a是左值，推导出T为int&，引⽤折叠，模板实例化为void Function(int& t)
//	Function(a); // 左值
//
//	// std::move(a)是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(std::move(a)); // 右值
//
//	const int b = 8;
//
//	// a是左值，推导出T为const int&，引⽤折叠，模板实例化为void Function(const int&t)
//	Function(b); // const 左值
//
//	// std::move(b)右值，推导出T为const int，模板实例化为void Function(const int&&t)
//	Function(std::move(b)); // const 右值
//
//	return 0;
//}


//参数匹配
class Myclass {
public:

	void func(int& r1) {
		cout << "void func(int&)" << endl;
	}

	void func(const int& r2) {
		cout << "void func(const int&)" << endl;
	}

	void func(int&& r3) {
		cout << "void func(int&&)" << endl;
	}

	void func(const int&& r4) {
		cout << "void func(const int&&)" << endl;
	}

private:
	int _a = 0;
	int _b = 0;;
};

int main() {

	int a = 20;

	int&& r1 = move(a);
	const int&& r2 = move(a);

	Myclass A;

	A.func(r1);
	A.func(forward<int>(r1));//这里传int和int&&是一样的
	A.func(forward<int&>(r1));

	A.func(forward<const int>(r2));
	A.func(forward<const int&>(r2));
	
	A.func(forward<int>(a));
	A.func(forward<int&>(a));
	

	return 0;

}